package com.ojoin.trade.common.utils.paynow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ojoin.trade.common.utils.Config;
import com.ojoin.trade.common.utils.LogUtils;
import com.ojoin.trade.common.utils.MD5;
import com.ojoin.trade.common.utils.json.JSONUtils;

/**
 * Created with IntelliJ IDEA.
 * User: Twar3
 * Date: 14-12-30
 * Time: 下午9:11
 * To change this template use File | Settings | File Templates.
 */
public class Unpack {

	private final static Logger logger = LoggerFactory
			.getLogger(Unpack.class);
    /**
     * 解密报文
     * @param dataStr 报文串
     * @param charset 编码字符集
     * @return
     */
    public List unpack(String dataStr, String charset){
        List respList = new ArrayList();

        try{
            dataStr = java.net.URLDecoder.decode(dataStr,charset);
        }catch (Exception e){
        	LogUtils.error(logger,e,"传入报文串：%s",dataStr);
            return respList;
        }

        String resp_code ;//响应码
        String code ;//功能代码
        String data ;//3DES的串
        String sign ;//MD5的签名
        
        String DSEKey = Config.getProperty("ipaynow.dsekey");//3DES需要的key
        String MD5Key = Config.getProperty("ipaynow.md5key");//MD5需要的key

        respList = this.base(dataStr);
        resp_code = (String)respList.get(0);
        if(!"00".equals(resp_code)){
            respList.clear();
            respList.add("01");
            respList.add("报文解析失败");
            LogUtils.info(logger,"返回：" + JSONUtils.toJSONString(respList));
            return respList;
        }
        code = (String)respList.get(1);
        data = (String)respList.get(2);
        sign = (String)respList.get(3);

        if("0".equals(code)){
            respList.clear();
            respList.add("01");
            respList.add(data);
            LogUtils.info(logger,"返回：" + JSONUtils.toJSONString(respList));
            return respList;
        }

        respList = this.DESMessage(data,DSEKey);
        resp_code = (String)respList.get(0);
        if(!"00".equals(resp_code)){
            respList.clear();
            respList.add("01");
            respList.add(data);
            LogUtils.info(logger,"返回：" + JSONUtils.toJSONString(respList));
            return respList;
        }
        Map<String, String> dataMap = (Map<String, String>)respList.get(1);

        respList = this.MD5Message(dataMap,MD5Key,sign);
        resp_code = (String)respList.get(0);
        if(!"00".equals(resp_code)){
            respList.clear();
            respList.add("01");
            respList.add(data);
            LogUtils.info(logger,"返回：" + JSONUtils.toJSONString(respList));
            return respList;
        }
        respList.clear();
        respList.add(resp_code);
        respList.add(dataMap);
//        LogUtils.info(logger,"返回：" + JSONUtils.toJSONString(respList));
        return respList;
    }

    /**
     * 解base64编码的串
     * @param dataStr 数据
     * @return
     */
    private List<String> base(String dataStr){
        List<String> respList = new ArrayList<String>();

        String code ;//临时存储第一部分
        String data = "";//功能代码
        String md5 = "";//机构码

        try{
            if(dataStr==null||"".equals(dataStr)){
            	LogUtils.info(logger,"解析base64失败");
                respList.add("01");
                respList.add("");
                return respList;
            }

            String[]  st = dataStr.split("\\|");
            code = st[0];

            if("1".equals(code)){
                data = new String(BASE64.decode(st[1]));
                md5 = new String(BASE64.decode(st[2]));
            }
            if("0".equals(code)){
                data = new String(BASE64.decode(st[1]));
            }
            respList.add("00");
            respList.add(code);
            respList.add(data);
            respList.add(md5);
        }catch (Exception e){
        	LogUtils.error(logger,e,"解析base64失败");
            respList.add("01");
            respList.add("报文解析失败");
            return respList;
        }
        return respList;
    }

    /**
     * 解密3DES密文
     * @param DSEStr 3DES密文
     * @param DSEKey 3DES的key
     * @return
     */
    private List DESMessage(String DSEStr,String DSEKey){
        List respList = new ArrayList();
        Map<String,String> map = new HashMap<String, String>();
        if(DSEStr==null||DSEKey==null){
        	LogUtils.info(logger,"3DESC密文或者密钥为空");
            respList.add("01");
            respList.add("报文解析失败");
            return respList;
        }
        String str = ThreeDESEncryptProvider.decrypt(DSEStr, DSEKey);//存储3DES解密的原文
        if(str==null||"".equals(str)){
        	LogUtils.info(logger,"3DESC原文为空");
            respList.add("01");
            respList.add("报文解析失败");
            return respList;
        }
        try {
            map = ReportParser.parseFormDataPatternReport(str, "utf-8");
        }catch (Exception e){
        	LogUtils.error(logger,e,"将3DES原文放入Map出错");
            respList.add("01");
            respList.add("报文解析失败");
            return respList;
        }

        respList.add("00");
        respList.add(map);
        return respList;
    }

    /**
     * 验证签名
     * @param map 数据
     * @param MD5Key MD5 key
     * @param sign 报文签名串
     * @return
     */
    private List<String> MD5Message(Map<String,String> map,String MD5Key,String sign){
        List<String> respList = new ArrayList<String>();
        if(map==null){
        	LogUtils.info(logger,"验证签名时原始数据为空");
            respList.add("01");
            respList.add("报文解析失败");
            return respList;
        }
        if(sign==null||"".equals(sign)){
        	LogUtils.info(logger,"原始签名为空");
            respList.add("01");
            respList.add("报文解析失败");
            return respList;
        }

        String toRSAStr = FormDateReportConvertor.postFormLinkReport(map);

        try {
            String signNow = MD5.md5(toRSAStr + MD5Key, "utf-8");
            if(!sign.equalsIgnoreCase(signNow)){
            	LogUtils.info(logger,"签名验证失败");
            	LogUtils.info(logger,"待生成签名的串：" + toRSAStr);
            	LogUtils.info(logger,"系统存储的key：" + MD5Key);
            	LogUtils.info(logger,"生成的签名串：" + signNow);
            	LogUtils.info(logger,"商户的签名串：" + sign);
                respList.add("01");
                respList.add("报文解析失败");
                return respList;
            }
        }catch (Exception e){
        	LogUtils.error(logger,e,"签名验证出错");
            respList.add("01");
            respList.add("报文解析失败");
            return respList;
        }
        respList.add("00");
        return respList;
    }

}
